package com.hzit.aspect;

import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.hzit.anno.RequirePermissions;
import com.hzit.constant.HzitConstants;
import com.hzit.entity.LoginUser;
import com.hzit.util.JwtUtil;
import com.hzit.util.ResponseUtil;
import io.jsonwebtoken.Claims;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.hamcrest.core.StringRegularExpression;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.List;
import java.util.Map;

/**
 * 类名：
 * 作者：WF
 * 功能：利用aop完成授权
 */
@Component
@Aspect
public class PreAuthorizeAspect {
	@Autowired
	private StringRedisTemplate redisTemplate;

	//1. 环绕通知(代表只要方法前有@RequirePermissions注解的都要经过这个环绕通知的方法)
	@Around("@annotation(requirePermissions)")
	public Object innerAround(ProceedingJoinPoint point, RequirePermissions requirePermissions) throws Throwable{
		//1.1 得到注解的值
		String[] value = requirePermissions.value();
		//1.2 得到redis中的登录用户
		LoginUser loginUser = getLoginUser();
		//1.3 将我们注解的值与权限串比较，是否在其中，在就放行
		hasPermissions(value,loginUser.getPermissions());
		//1.4 调用环绕通知的方法
		return point.proceed();
	}
	// 判断是否有访问资源的权限
	private void hasPermissions(String[] value, List<String> permissions) {
		if (!permissions.contains(value[0])) {
			throw new RuntimeException("对不起，你没有访问资源的权限！");
		}

	}
	// 获取登录用户
	private LoginUser getLoginUser() {
		//1. 获取ServletRequestAttributes对象
		ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
		//2. 得到请求对象
		HttpServletRequest request = requestAttributes.getRequest();
		//3. 得到请求头,并得到token的值
		String token = getToken(request);
		//4. 使用Jwt解析token
		Claims claims = JwtUtil.parseToken(token);
		Map<String,Object> map = (Map<String, Object>) claims.get(HzitConstants.JWT_TOKEN_KEY);
		String uuidToken = map.get(HzitConstants.USER_KEY).toString();
		//5. 获取redis的key
		String key = getKey(uuidToken);
		//6. 根据redis的key得到值
		String loginUserStr = redisTemplate.opsForValue().get(key);
		//7. 解析登录用户
		return JSONUtil.toBean(loginUserStr, LoginUser.class);
	}
	// 拼装redis的key
	private String getKey(String uuidToken) {
		return HzitConstants.REDIS_KEY_PREFIX + uuidToken;
	}

	// 获取请求头信息
	private String getToken(HttpServletRequest request) {
		String header = request.getHeader(HzitConstants.REQUEST_HEADER_AUTHORIZATION);
		return header.replace(HzitConstants.REQUEST_HEADER_BEARER, "");
	}
}
